import numpy as np
import torch

# pytorch默认是FloatTensor格式
# 设置默认类型
# torch.set_default_tensor_type(torch.DoubleTensor)

a = torch.randn(2, 4)  # 随机初始化2行4列的矩阵
# torch.FloatTensor
# <class 'torch.Tensor'>
print(a.type())
print(type(a))
print(a)

# 判断类型
print(isinstance(a, torch.FloatTensor))
# 如果是部署在gpu就用属于cuda类型
print(isinstance(a, torch.cuda.FloatTensor))

# 标量
# 会根据类型自动判断
print(torch.tensor(1.))  # 标量
print(torch.tensor(1.3).type())  # torch.FloatTensor

# 创建张量
print("创建张量---------->")
print(torch.tensor(1.))
print(torch.tensor([1.1]))

print("获取维度---------》")
# 获取tensor维度 torch.tensor(1.).shape
print(torch.tensor(1.).size())  # 0维
print(torch.tensor([1]).shape)  # 1维
print(torch.tensor([2, 2]).shape)  # 2维
print(torch.randn(2, 3, 2, 2).dim())  # 4维
# print(torch.tensor())

# 将标量转为数字
print("将张量转为数字")
print(torch.tensor(1.25).item())
print(torch.tensor([1.]).item())
# print(torch.tensor([2, 2]).item())  只能转换0维、1维数据


# 计算占用内存数量
print(torch.randn(2, 3, 2, 2).numel())  # 2*3*2*2

# numpy导入数据
print("numpy导入数据---------------->")
data = np.array([2, 2.2])
print(torch.from_numpy(data))
print(torch.from_numpy(np.array([[1, 2], [2, 2]])))

print("初始化数据------------》")
# 弊端数据不是很多就是很小 使用时一定要覆盖数据
# print(torch.empty(2, 2))
# print(torch.FloatTensor(2, 2))  # 初始化创建2维 2列数据
# print(torch.FloatTensor(2, 3, 2, 2))  # 初始化创建2batch 3维 2行 2列数据
# print(torch.IntTensor(2, 3, 2, 2))

# 随机创建矩阵
print("随机创建矩阵------>")
# print(torch.randn(2, 2))  # 2行2列
# print(torch.randn(2, 3, 2, 2))  # 2batch 3维度 2行 2列
#
# print(torch.FloatTensor(2))  # 初始化创建1维 2列数据  tensor([-1.0842e-19,  1.8875e+00])
# print(torch.ones(2, 3, 2, 2))  # 创建数据全为1 2batch 3维 2行 2列数据
# 将numpy转为tensor
# print(torch.from_numpy(np.ones((2, 3, 2, 2))))  # 使用numpy创建数据全为1 2batch 3维 2行 2列数据
# print(torch.zeros(2, 3, 2, 2))  # 创建数据全为0 2batch 3维 2行 2列数据
# 随机创建torch.ones(2, 2).shape 维度的数据
# print(torch.randn_like(torch.ones(2, 2)))
# 随机创建1到9数字 3行3列
# print(torch.randint(1, 10, [3, 3]))
# print(torch.randint(1, 10, torch.ones(2, 2).size()))
# print(torch.randint(1, 10, torch.ones(2, 2).shape))
# 对角为1的矩阵
# print(torch.eye(3, 4))

# 随机打散 将给定数字随机打散
print(torch.randperm(5))

print("自定义方差--------------》")
print(torch.normal(mean=torch.full([10], 0.), std=torch.arange(1, 0, -0.1)))

# 向量操作
print("向量操作------------->")
# 0 到 20 [0,20) 2步长
print(torch.arange(0, 20, 2))

# 数据等分 [2,20]平均分为4份
print(torch.linspace(0, 20, steps=4))
# 1到0  10**0 10**0.9 10**0.8 ...  10**0.1
print(torch.linspace(0, -1, steps=10))

# 改变向量维度
print(torch.arange(0, 18, 2).reshape(3, 3))
print(torch.arange(0, 20, 2).reshape(2, 5))

# 将向量全部改为某个数
print(torch.full([2, 5], 1))
print(torch.full([], 1).item())

# 索引 、切片
# 2:   2到最后个
# :2    第一个到第2个
# ::2   每隔1个
print("索引获取数据----------->")
print(torch.randn(2, 3, 2, 2).shape)
print(list(torch.randn(2, 3, 2, 2).shape))
print(torch.randn(2, 3, 2, 2)[0])
print(torch.randn(2, 3, 2, 2)[0].shape)

data = torch.randn(2, 3, 6, 6)

print(data[1][2])
# 等价于
print(data[1, 2])
print(data[1, 2, 1, 0])
# ：2 正序从第一个到2个
print(data[:2, :, :, :].shape)
# 后面的 ：可以不写
print(data[:2].shape)

# -1索引倒序到最后一个
print(data[:1, -1:].shape)
# 1: 索引第一个到最后一个
print(data[:1, 1:].shape)
# 起始：结尾：步长  或者 ：：2
print(data[:, :, 0:6:2, 0:6:2].shape)
print(data[:, :, ::2, ::2])

# 索引获取
print(data.index_select(0, torch.tensor([0, 1])))

# .代表任意多
d = torch.randn(5, 3, 28, 28)
print(d[...].shape)
print(d[1, ...].shape)
print(d[:, 1, ...].shape)
print(d[..., 2:].shape)

# mask掩码
print("mask掩码---------------->")
x = torch.randn(3, 4)
print(x)
# 大于0.5
mask = x.ge(0.5)
# 小于
# x.lt()

print(mask)
print(torch.masked_select(x, mask=mask))

y = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(torch.take(y, torch.tensor([0, 1, 2])))
